package me.seawenc.db.checker.dbengine.impl.utils;

import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
import java.util.stream.Collectors;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import me.seawenc.db.checker.bean.FileConfig;
import me.seawenc.db.checker.helper.ExecTimeCost;
import me.seawenc.db.checker.helper.Log;

/**
 * sql执行器
 */
public class SqlActuator {
    /** 数据库连接 **/
    protected Connection jdbcConn;
    /**
     * 初始化数据库连接
     * @param jdbcInfo 传入jdbc信息
     */
    public SqlActuator(FileConfig jdbcInfo) throws Exception {
        Properties properties = new Properties();
        properties.setProperty("user", jdbcInfo.getJdbcUser());
        properties.setProperty("password", jdbcInfo.getJdbcPwd());
        FileConfig jdbc= JSONObject.parseObject(JSON.toJSONString(jdbcInfo), FileConfig.class);
        beforeDsTypeInit(jdbc,properties);
        try {
            Class.forName(jdbcInfo.getJdbcDriver());
            jdbcConn = DriverManager.getConnection(jdbc.getJdbcUrl(), properties);
        } catch (Exception throwables) {
            Log.error("获得jdbc连接失败!,msg:" + throwables.getMessage(),throwables);
            throw throwables;
        }
    }

    /**
     * 让子类覆盖，不同种类的jdbc，初始化可能不用
     * @param jdbcInfo
     * @param properties
     */
    protected void beforeDsTypeInit(FileConfig jdbcInfo, Properties properties) throws IOException {
    }
    /**
     * 执行查询sql
     * @param sql
     * @return
     * @throws SQLException
     */
    public List<JSONObject> execQuerySql(String sql) throws Exception {
        //过滤掉注释，去掉换行
        sql=Arrays.stream(sql.split("\n")).filter(v-> !v.startsWith("--")).collect(Collectors.joining(" "));
        ExecTimeCost cost=new ExecTimeCost();
        List<JSONObject> ret=new ArrayList<>();
        Log.debug("开始执行sql:"+sql);
        if (jdbcConn != null) {
            ret=execJdbcSql(sql);
        }
        Log.debug(String.format("exec sql,cost:%s,ret size:%s,sql:%s",cost.getFormat(),ret.size(),sql));
        return ret;
    }

    protected List<JSONObject> execJdbcSql(String sql) throws SQLException {
        Statement stmt = jdbcConn.createStatement();
        List<JSONObject> rets= new ArrayList<>();
        try {
            ResultSet rs= stmt.executeQuery(sql);
            ResultSetMetaData rsmd = rs.getMetaData() ;
            int columnCount = rsmd.getColumnCount();
            while (rs.next()) {
                JSONObject row=new JSONObject(true);
                for(int i=1;i<=columnCount;i++){
                    row.put(rsmd.getColumnName(i),rs.getObject(i)+"");
                }
                rets.add(row);
            }
            return rets;
        }catch (SQLException e){
            Log.error(String.format("执行sql出错sql=%s,msg=%s", sql, e.getMessage()));
            throw e;
        }finally {
            stmt.close();
        }
    }

    public void close() throws SQLException {
        if(jdbcConn!=null){
            jdbcConn.close();
        }
    }
}
